﻿using CloudStorageLight.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Principal;
using System.Text.RegularExpressions;
using System.Web;

namespace CloudStorageLight.Web.Models
{
    public class AppBlobUser : BlobUser
    {
        static IPrincipal CreatePrincipal(IPrincipal user, string[] roles)
        {
            if (user.Identity.IsAuthenticated)
            {
                var cloudAccount = BlobService.GetCurrentCloudAccount();
                if (cloudAccount != null && cloudAccount.AzureAdMode)
                {
                    try
                    {
                        var authority = cloudAccount.Authority;
                        var cloudStorageLightAppKey = cloudAccount.CloudStorageLightAppKey;
                        var cloudStorageLightClientId = cloudAccount.CloudStorageLightClientId;
                        var tenantId = cloudAccount.TenantId;
                        //user = AzureAdUtil.CreatePrincipal(authority, cloudStorageLightClientId, cloudStorageLightAppKey, tenantId, user.Identity.Name);
                        var group = AzureAdUtil.ListGroupOfMember(authority, cloudStorageLightClientId, cloudStorageLightAppKey, tenantId, user.Identity.Name);
                        group = group ?? new string[] { };
                        if (roles != null) group = group.Concat(roles);
                        group = group.Select(x => x.ToLower()).ToArray();
                        user = new GenericPrincipal(new GenericIdentity(user.Identity.Name), (string[])group);

                    }
                    catch (Exception ex)
                    {
                        LogError(cloudAccount, ex.ToString());
                        Debug.WriteLine(ex.ToString());
                        return user;
                    }

                }
            }
            return user;
        }
        static void LogError(CloudAccount account, string message)
        {
            if (HttpContext.Current == null) return;
            try
            {
                var svc = new LogService(SystemSettings.Instance.BlobStorage);
                svc.EntryLog(HttpContext.Current.User.Identity.Name, account.AccountName, "Error", HttpContext.Current.Request.Url.PathAndQuery, message, HttpContext.Current.Application);
            }
            catch
            {
            }
        }

        static void LogInfo(CloudAccount account, string message)
        {
            try
            {
                var svc = new LogService(SystemSettings.Instance.BlobStorage);
                svc.EntryLog(HttpContext.Current.User.Identity.Name, account.AccountName, "Info", HttpContext.Current.Request.Url.PathAndQuery, message, HttpContext.Current.Application);
            }
            catch
            {
            }
        }

        public ApplicationUser AppUser { get; set; }

        public string[] Role { get; set; }

        public AppBlobUser(ApplicationUser user, string[] role)
            : this(CreatePrincipal(new GenericPrincipal(new GenericIdentity(user.UserName), role), role), BlobService.GetCurrentCloudAccount())
        {
            AppUser = user;
            Role = role;
        }

        public AppBlobUser(ApplicationUser user, string[] role, CloudAccount account)
            : this(CreatePrincipal(new GenericPrincipal(new GenericIdentity(user.UserName), role), role), account)
        {
            AppUser = user;
            Role = role;

        }

        public AppBlobUser(IPrincipal principal)
            : this(CreatePrincipal(principal, null), BlobService.GetCurrentCloudAccount())
        {

        }

        public AppBlobUser(IPrincipal principal, CloudAccount cloudAccount)
            : base(principal)
        {
            if (cloudAccount != null)
            {
                if (cloudAccount.AzureAdMode)
                {
                    IsAdmin = cloudAccount.GetAdministrators().Any(x => string.Equals(x, this.Name, StringComparison.InvariantCultureIgnoreCase));
                    if (string.Equals(cloudAccount.EMailAddress, this.Name, StringComparison.InvariantCultureIgnoreCase)) IsAdmin = true;
                }
                else
                {
                    var claims = ((System.Security.Claims.ClaimsIdentity)principal.Identity).Claims;
                    var admin = claims.FirstOrDefault(x => string.Equals(x.Value, "true", StringComparison.InvariantCultureIgnoreCase) && x.Type == "AdminAuthenticate");
                    if (admin != null)
                    {
                        IsAdmin = HasAdminRole(cloudAccount);
                    }
                    if (!cloudAccount.CanAccess(Name, false)) IsGuest = true;
                }
            }
        }

        public bool HasAdminRole(CloudAccount cloudAccount)
        {
            if (cloudAccount.GetAdministrators().Any(x => string.Equals(x, this.Name, StringComparison.InvariantCultureIgnoreCase))) return true;
            if (string.Equals(cloudAccount.EMailAddress, this.Name, StringComparison.InvariantCultureIgnoreCase)) return true;
            return false;
        }

        public override bool IsInRole(string role)
        {
            if (role == GetDomain()) return true;
            return base.IsInRole(role);
        }

        public string GetDomain()
        {
            var items = this.Name.ToLower().Split('@');
            if (items.Length <= 1) return null;
            return items[items.Length - 1];
        }

        public static string GetDomain(string username)
        {
            var items = username.Split('@');
            if (items.Length <= 1) return null;
            return items[items.Length - 1].ToLower();
        }

        public static string GetDomainEscape(string username)
        {
            var items = username.Split('@');
            if (items.Length <= 1) return null;
            return items[items.Length - 1].Replace("_", "-").Replace(".", "-").ToLower();
        }
    }
}